﻿using System;
using System.IO;
using __Able.Network.Connection;
using System.Net;
using __Able.Network.Utils;

namespace __Able.Network.Manager
{
    /// <summary>
    /// 连接管理
    /// </summary>
    public class ConnectionManager : IDisposable
    {
        /// <summary>
        /// 信道实例
        /// </summary>
        public Channel channel { get; private set; }
        /// <summary>
        /// 连接池
        /// </summary>
        public IConnectionPool ConnectionPool { get; private set; }
        
        /// <summary>
        /// Initializes a new instance of the <see cref="ConnectionManager"/> class.
        /// </summary>
        /// <param name="client">The client.</param>
        internal ConnectionManager(Channel channel)
        {
            this.channel = channel;
            this.ConnectionPool = new ConnectionPool();
        }
        internal ConnectionManager() { }

        /// <summary>
        /// 用户可以使用这个方法更改连接池的实现
        /// </summary>
        /// <param name="pool">The pool.</param>
        public void SetConnectionPool(IConnectionPool pool)
        {
            this.ConnectionPool = pool;
        }
        /// <summary>
        /// 确认指定的PortName的连接存在
        /// </summary>
        /// <param name="serverHost">The server host.</param>
        /// <param name="port">The port.</param>
        /// <param name="portName">Name of the port.</param>
        /// <param name="start">if set to <c>true</c> [start].</param>
        public bool EnsureConnection(string port, bool start)
        {
            if (ConnectionPool.HasConnection(port) && ConnectionPool.GetConnection(port).IsConnected)
                return true;
            else
            {
                IConnection conn = Create("127.0.0.1", port, start);
                if (conn == null)
                {
                    return false;
                }
            }
            return true;
        }

        private IConnection Create(string serverHost, string port, bool start)
        {
            IConnection conn = null;
            ConnectionPolicy policy = null;
            EndPoint server = Util.GetEndPoint(serverHost, Convert.ToInt32(port));
            policy = new ConnectionPolicy(channel, port, (uint)_ProtocolFamily.PROTOCOL_FAMILY_BASIC,
                (byte)_ProtocolFamily.PROTOCOL_FAMILY_BASIC);

            //if (channel.IsUdp)
            //{
            //    conn = client.ConnectionManager.ConnectionPool.NewUDPConnection(policy, server, start);
            //}
            //else
            conn = channel.ConnectionManager.ConnectionPool.NewTCPConnection(policy, server, start);
            return conn;
        }

        /// <summary>
        /// 根据连接名称获得连接
        /// </summary>
        /// <param name="port">port.</param>
        public IConnection GetConnection(string port)
        {
            return ConnectionPool.GetConnection(port);
        }
        /// <summary>
        /// 一般网络错误事件
        /// </summary>
        public event EventHandler<ErrorEventArgs> NetworkError;

        /// <summary>
        /// 网络连接成功
        /// </summary>
        public event EventHandler ConnectSuccessfully;

        /// <summary>
        /// 连接服务器失败
        /// </summary>
        public event EventHandler<ErrorEventArgs> ConnectServerError;
        /// <summary>
        /// Raises the event.
        /// </summary>
        /// <param name="e">The instance containing the event data.</param>
        internal void OnConnectServerError(Exception e)
        {
            if (ConnectServerError != null)
            {
                ConnectServerError(this, new ErrorEventArgs(e));
            }
        }
        /// <summary>
        /// Called when [network error].
        /// </summary>
        /// <param name="e">The e.</param>
        internal protected void OnNetworkError(Exception e)
        {
            if (NetworkError != null)
            {
                NetworkError(this, new ErrorEventArgs(e));
            }
        }
        /// <summary>
        /// Called when [connect successed].
        /// </summary>
        internal protected void OnConnectSuccessfully()
        {
            if (ConnectSuccessfully != null)
            {
                ConnectSuccessfully(this, EventArgs.Empty);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        public void Dispose()
        {
            ConnectionPool.Dispose();
        }
    }
}
